package com.abe.bathsystem.android.service;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.text.TextUtils;

import com.abe.bathsystem.android.v3.MainBathAbsActivity;
import com.abe.bathsystem.base.ManagerAPP;
import com.abe.bathsystem.entity.PushSocketData;
import com.abe.bathsystem.entity.http.HttpGPushEntity;
import com.abe.libcore.utils.normal.CommonUtils;
import com.abe.libcore.utils.normal.ConstantCore;
import com.google.gson.Gson;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.NoRouteToHostException;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.Timer;
import java.util.TimerTask;

/**
 * socket连接服务
 */
public class SocketService extends Service {
    public static final String SOCKET_MESSAGE = "com.abe.socket.message";
    public static final String SOCKET_STATUS = "socketStatus";
    public static final String SOCKET_MSG = "socketMessage";
    public static final String bm = "utf-8"; // 全局定义，以适应系统其他部分
    /*数据*/
    private String IP;
    private int port;
    private String roomId;
    /*socket*/
    private Socket socket;
    /*连接线程*/
    private Thread connectThread;
    private Timer timer = new Timer();
    private OutputStream outputStream;
    /*读线程*/
    private boolean isReading;
    private ReadThread readThread;
    private BufferedReader in = null;

    private SocketBinder socketBinder = new SocketBinder();
    private TimerTask task;

    /*默认重连*/
    private boolean isReConnect = true;

    //private Handler handler = new Handler(Looper.getMainLooper());

    @Override
    public IBinder onBind(Intent intent) {
        CommonUtils.w("SocketService-onBind");
        return socketBinder;
    }

    public class SocketBinder extends Binder {
        /*返回SocketService 在需要的地方可以通过ServiceConnection获取到SocketService  */
        public SocketService getService() {
            return SocketService.this;
        }
    }


    @Override
    public void onCreate() {
        super.onCreate();
        CommonUtils.w("SocketService-onCreate");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        CommonUtils.w("SocketService-onStartCommand");
        if (intent != null && intent.getExtras() != null) {
            IP = intent.getExtras().getString("ip");
            port = intent.getExtras().getInt("port");
            roomId = intent.getExtras().getString("roomId");
            isReading = false;
            /*开启计时器*/
            startTimer();
            /*初始化socket*/
            initSocket();
        }
        return super.onStartCommand(intent, flags, startId);
    }


    /*初始化socket*/
    private void initSocket() {
        CommonUtils.w("SocketService-initSocket");
        if (socket == null && connectThread == null) {
            connectThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    socket = new Socket();
                    try {
                        /*超时时间为2秒*/
                        socket.connect(new InetSocketAddress(IP, port), 2000);
                        /*连接成功的话  发送心跳包*/
                        if (socket.isConnected()) {
                            /*因为Toast是要运行在主线程的  这里是子线程  所以需要到主线程哪里去显示toast*/
                            //toastMsg("socket已连接");
                            /*发送连接成功的消息*/
                            sendMsg(SOCKET_STATUS, "success:socket已连接");
                            if (readThread == null || !isReading) {
                                readThread = new ReadThread();
                                readThread.start();
                            }
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                        if (e instanceof SocketTimeoutException) {
                            //toastMsg("连接超时，正在重连");
                            sendMsg(SOCKET_STATUS, "fail:连接超时，正在重连");
                        } else if (e instanceof NoRouteToHostException) {
                            //toastMsg("地址不存在，请检查");
                            sendMsg(SOCKET_STATUS, "fail:地址不存在，请检查");
                        } else if (e instanceof ConnectException) {
                            //toastMsg("连接异常或被拒绝，请检查");
                            sendMsg(SOCKET_STATUS, "fail:连接异常或被拒绝，请检查");
                        }
                    }
                }
            });
            /*启动连接线程*/
            connectThread.start();
        }
    }

    private void sendMsg(String type, String info) {
        CommonUtils.saveLocalDailyLog(MainBathAbsActivity.getRealTime(), info, ConstantCore.LOG_SOCKET_PATH);
        Bundle bundle = new Bundle();
        switch (type) {
            case SOCKET_STATUS: {
                PushSocketData<String> data = new PushSocketData<>(type, info);
                bundle.putSerializable(SOCKET_MESSAGE, data);
            }
            break;
            case SOCKET_MSG: {
                HttpGPushEntity entity = new Gson().fromJson(info, HttpGPushEntity.class);
                if (entity == null) return;
                PushSocketData<HttpGPushEntity> data = new PushSocketData<>(type, entity);
                bundle.putSerializable(SOCKET_MESSAGE, data);
            }
            break;
        }
        CommonUtils.sendLocalBroadcast(SOCKET_MESSAGE, bundle);
    }

    /*因为Toast是要运行在主线程的   所以需要到主线程哪里去显示toast*/
    //private void toastMsg(final String msg) {
    //handler.post(new Runnable() {
    //@Override
    //public void run() {
    //Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
    //}
    //});
    //}

    /*发送数据*/
    public void sendOrder(final String order) {
        CommonUtils.w("SocketService-sendOrder");
        if (socket != null && socket.isConnected()) {
            /*发送指令*/
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        outputStream = socket.getOutputStream();
                        if (outputStream != null) {
                            outputStream.write((order).getBytes(bm));
                            outputStream.flush();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            //} else {
            //toastMsg("socket连接错误,请重试");
        }
    }

    /**
     * 读数据线程
     */
    private class ReadThread extends Thread {
        @Override
        public void run() {
            super.run();
            isReading = true;
            while (!isInterrupted() && isReading) {
                try {
                    if (socket != null && socket.isConnected()) {
                        in = new BufferedReader(new InputStreamReader(
                                socket.getInputStream(), bm));
                        char[] buffer = new char[8000];
                        int count;
                        if ((count = in.read(buffer)) > 0) {
                            char[] temp = new char[count];
                            System.arraycopy(buffer, 0, temp, 0, count);
                            String value = new String(temp);
                            sendMsg(SOCKET_MSG, value);
                        }
                    } else {
                        isReading = false;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    isReading = false;
                }
            }
        }
    }

    private static final int DEFAULT_BEAT_TIME = 5 * 60 * 1000;//五分钟

    //启动计时器
    private void startTimer() {
        /*
         * java.util.Timer.schedule(TimerTask task, long delay, long period)：
         * 这个方法是说，delay/1000秒后执行task,然后进过period/1000秒再次执行task，
         * 这个用于循环任务，执行无数次，当然，你可以用timer.cancel();取消计时器的执行。
         */
        timer = new Timer();
        task = new StillTimerTask();
        try {
            timer.schedule(task, 0, DEFAULT_BEAT_TIME);
        } catch (IllegalStateException e) {
            e.printStackTrace();
            timer = new Timer();
            task = new StillTimerTask();
            timer.schedule(task, 0, DEFAULT_BEAT_TIME);
        }
    }

    private class StillTimerTask extends TimerTask {

        @Override
        public void run() {
            if (socket != null && socket.isConnected()) {
                CommonUtils.w("SocketService-sendBeatData");
                try {
                    if (!TextUtils.isEmpty(roomId)) {
                        outputStream = socket.getOutputStream();
                        /*这里的编码方式根据你的需求去改*/
                        outputStream.write(roomId.getBytes(bm));
                        outputStream.flush();
                    }
                } catch (Exception e) {
                    /*发送失败说明socket断开了或者出现了其他错误*/
                    //toastMsg("连接断开，正在重连");
                    sendMsg(SOCKET_STATUS, "连接断开，正在重连");
                    /*重连*/
                    releaseSocket();
                    e.printStackTrace();
                }
            } else {
                //重连
                releaseSocket();
            }
        }
    }

    /*释放定时重连定时器*/
    private void releaseTimer() {
        if (task != null) {
            task.cancel();
            task = null;
        }
        if (timer != null) {
            timer.purge();
            timer.cancel();
            timer = null;
        }
    }

    /*释放资源*/
    private void releaseSocket() {
        CommonUtils.w("SocketService-releaseSocket");
        isReading = false;
        if (readThread != null) {
            readThread.interrupt();
            readThread = null;
        }
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            in = null;
        }
        if (outputStream != null) {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            outputStream = null;
        }
        if (socket != null) {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            socket = null;
        }
        if (connectThread != null) {
            connectThread = null;
        }
        /*重新初始化socket*/
        if (isReConnect) {
            initSocket();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        CommonUtils.w("SocketService-onDestroy");
        isReConnect = false;
        releaseTimer();
        releaseSocket();
    }
}
